#include "lapi.h"
#include "lapi_comm.h"
#include "lapi_setting.h"

LAPI_SETTING_S g_lapi_setting;
LAPI_SETTING_S g_lapi_setting_bk;

static int lapi_copy_default_setting()
{
    struct stat f_stat;
    struct stat buf;
    //char cmd[200];

     if (stat(LAPI_DEFAULT_SETTING_FILE, &f_stat) != 0) {
        LAPI_ERR("Can not load default setting since the file %s does not exist", LAPI_SETTING_FILE);
        return -1;
    }

     if (lstat(LAPI_SETTING_FILE_DIR, &buf) < 0) {
         mkdir(LAPI_SETTING_FILE_DIR, 0777);
     } else {
         if (!S_ISDIR(buf.st_mode)) {
            unlink(LAPI_SETTING_FILE_DIR);
            mkdir(LAPI_SETTING_FILE_DIR, 0777);
        }
     }

    //memset(cmd, 0, 200);
    //sprintf(cmd, "busybox cp %s %s", LAPI_DEFAULT_SETTING_FILE, LAPI_SETTING_FILE_DIR);
    //system(cmd);
    
    FILE *flog = NULL;
    flog = fopen(LAPI_SETTING_FILE, "w+");
    if (flog == NULL) {
        LAPI_ERR("Failed to open %s", LAPI_SETTING_FILE);
        return -1;
    }
    fclose(flog);

    LAPI_DBG("Setting %s saved", LAPI_SETTING_FILE);
    chmod(LAPI_SETTING_FILE, 0666);


    if (stat(LAPI_SETTING_FILE, &f_stat) == 0) {
        LAPI_DBG("Load default setting sucess");
        return 0;
    }else{
        LAPI_ERR("Load default setting fail");
        return -1;
    }

}

void lapi_print_setting()
{
    LAPI_DBG("* Begin of LAPI_SETTING_S *");
    switch (g_lapi_setting.method) {
        case LAPI_LOCATION_METHOD_STANDALONE:
            LAPI_DBG("%s=%s", ATTR_LOC_METHOD, "STAND");
            break;
        case LAPI_LOCATION_METHOD_AUTONOMOUS:
            LAPI_DBG("%s=%s", ATTR_LOC_METHOD, "AUTO");
            break;
        case LAPI_LOCATION_METHOD_MS_ASSISTED:
            LAPI_DBG("%s=%s", ATTR_LOC_METHOD, "MSA");
            break;
        case LAPI_LOCATION_METHOD_MS_BASED:
            LAPI_DBG("%s=%s", ATTR_LOC_METHOD, "MSB");
            break;
        default:
            LAPI_DBG("%s=%s", ATTR_LOC_METHOD, "BAD");
            break;
    }
    switch (g_lapi_setting.reset) {
        case LAPI_RESET_TYPE_COLD_RESET:
            LAPI_DBG("%s=%s", ATTR_RST_TYPE, "COLD");
            break;
        case LAPI_RESET_TYPE_HOT_RESET:
            LAPI_DBG("%s=%s", ATTR_RST_TYPE, "HOT");
            break;
        case LAPI_RESET_TYPE_FACTORY_RESET:
            LAPI_DBG("%s=%s", ATTR_RST_TYPE, "FACTORY");
            break;
        default:
            LAPI_DBG("%s=%s", ATTR_RST_TYPE, "BAD");
            break;
    }
    LAPI_DBG("%s=%s", ATTR_SRV_ADDR, g_lapi_setting.srv_addr);
    LAPI_DBG("%s=%d", ATTR_SRV_PORT, g_lapi_setting.srv_port);
    LAPI_DBG("%s=%d", ATTR_QOS_HOR, g_lapi_setting.qos.hor_accuracy);
    LAPI_DBG("%s=%d", ATTR_QOS_VER, g_lapi_setting.qos.ver_accuracy);
    LAPI_DBG("%s=%d", ATTR_QOS_TIMEOUT, g_lapi_setting.qos.timeout);
    LAPI_DBG("%s=%d", ATTR_FIX_INTERVAL, g_lapi_setting.interval);
    LAPI_DBG("%s=%s", ATTR_IMSI, g_lapi_setting.imsi);
    LAPI_DBG("%s=%s", ATTR_LAC, g_lapi_setting.lac);
    LAPI_DBG("%s=%s", ATTR_CID, g_lapi_setting.cid);
    LAPI_DBG("%s=%s", ATTR_GPRS_DEV, g_lapi_setting.gprs_dev);
    //LAPI_DBG("%s=%d", ATTR_GPRS_PRO, g_lapi_setting.gprs_pro);
    LAPI_DBG("%s=%s", ATTR_CA_PATH, g_lapi_setting.ca_path);
    switch (g_lapi_setting.assist_pro) {
        case LAPI_ASSIST_PROTOCOL_USER_PLANE:
            LAPI_DBG("%s=%s", ATTR_ASSIST_PROTOCOL, "USER_PLANE");
            break;
        case LAPI_ASSIST_PROTOCOL_CONTROL_PLANE:
            LAPI_DBG("%s=%s", ATTR_ASSIST_PROTOCOL, "CONTROL_PLANE");
            break;
    }
    LAPI_DBG("%s=%s", ATTR_NW_OP, g_lapi_setting.nw_op);
    LAPI_DBG("%s=%s", ATTR_NW_TYPE, g_lapi_setting.nw_type);
    LAPI_DBG("* End of LAPI_SETTING_S *");
}

static int lapi_save_setting()
{
    FILE *fp = NULL;

    fp = fopen(LAPI_SETTING_FILE, "w+");
    if (fp == NULL) {
        LAPI_ERR("Failed to open %s", LAPI_SETTING_FILE);
        return -1;
    }

    fprintf(fp, "%s=", ATTR_LOC_METHOD);
    switch (g_lapi_setting.method) {
        case LAPI_LOCATION_METHOD_STANDALONE:
            fprintf(fp, "%s\n", "STAND");
            break;
        case LAPI_LOCATION_METHOD_AUTONOMOUS:
            fprintf(fp, "%s\n", "AUTO");
            break;
        case LAPI_LOCATION_METHOD_MS_ASSISTED:
            fprintf(fp, "%s\n", "MSA");
            break;
        case LAPI_LOCATION_METHOD_MS_BASED:
            fprintf(fp, "%s\n", "MSB");
            break;
        default:
            fprintf(fp, "%s\n", "STAND");
            break;
    }
    fprintf(fp, "%s=", ATTR_RST_TYPE);
    switch (g_lapi_setting.reset) {
        case LAPI_RESET_TYPE_COLD_RESET:
            fprintf(fp, "%s\n", "COLD");
            break;
        case LAPI_RESET_TYPE_HOT_RESET:
            fprintf(fp, "%s\n", "HOT");
            break;
        case LAPI_RESET_TYPE_FACTORY_RESET:
            fprintf(fp, "%s\n", "FACTORY");
            break;
        default:
            fprintf(fp, "%s\n", "COLD");
            break;
    }
    fprintf(fp, "%s=%s\n", ATTR_SRV_ADDR, g_lapi_setting.srv_addr);
    if (g_lapi_setting.srv_port == 0)
        fprintf(fp, "%s=\n", ATTR_SRV_PORT);
    else
        fprintf(fp, "%s=%d\n", ATTR_SRV_PORT, g_lapi_setting.srv_port);
    fprintf(fp, "%s=%d\n", ATTR_QOS_HOR, g_lapi_setting.qos.hor_accuracy);
    fprintf(fp, "%s=%d\n", ATTR_QOS_VER, g_lapi_setting.qos.ver_accuracy);
    fprintf(fp, "%s=%d\n", ATTR_QOS_TIMEOUT, g_lapi_setting.qos.timeout);
    fprintf(fp, "%s=%d\n", ATTR_FIX_INTERVAL, g_lapi_setting.interval);
    //fprintf(fp, "%s=%d\n", ATTR_GPRS_PRO, g_lapi_setting.gprs_pro);
    fprintf(fp, "%s=%s\n", ATTR_CA_PATH, g_lapi_setting.ca_path);
    switch (g_lapi_setting.assist_pro) {
        case LAPI_ASSIST_PROTOCOL_USER_PLANE:
            fprintf(fp, "%s=%s\n", ATTR_ASSIST_PROTOCOL, "USER_PLANE");
            break;
        case LAPI_ASSIST_PROTOCOL_CONTROL_PLANE:
            fprintf(fp, "%s=%s\n", ATTR_ASSIST_PROTOCOL, "CONTROL_PLANE");
            break;
        default:
            fprintf(fp, "%s=%s\n", ATTR_ASSIST_PROTOCOL, "USER_PLANE");
            break;
    }

    fflush(fp);
    fclose(fp);

    LAPI_DBG("Setting %s saved", LAPI_SETTING_FILE);

    return 0;
}

/*
 * generate a default setting if setting file missing or corrupted
 */
/*static void lapi_default_setting()
{
    g_lapi_setting.method = LAPI_LOCATION_METHOD_STANDALONE;
    g_lapi_setting.reset = LAPI_RESET_TYPE_HOT_RESET;
    strcpy(g_lapi_setting.srv_addr, "221.176.0.55");
    g_lapi_setting.srv_port = 7275;
    g_lapi_setting.qos.hor_accuracy = 75;
    g_lapi_setting.qos.ver_accuracy = 75;
    g_lapi_setting.qos.timeout = 240;
    g_lapi_setting.interval = 5;
    //g_lapi_setting.gprs_pro = 1;
    strcpy(g_lapi_setting.ca_path, "/system/location/AGPS_CA.pem");
    g_lapi_setting.assist_pro = LAPI_ASSIST_PROTOCOL_USER_PLANE;

    lapi_save_setting();

    //lapi_print_setting();
}*/

/*
 * parser key=value pair
 */
static int lapi_get_setting(char* line)
{
    char *pos;
    char key[LAPI_SETTING_LINE_LEN];
    char val[LAPI_SETTING_LINE_LEN];
    int i;

    /* trim the '\n' end of the line */
    /*pos = line;
    while (*pos != '\n')
        pos++;
    *pos = '\0';
    LAPI_DBG("line after trim: %s", line);*/

    pos = line;
    i = 0;
    memset(key, 0, LAPI_SETTING_LINE_LEN);
    while (*pos != '=')
        key[i++] = *pos++;
    pos++;

    i = 0;
    memset(val, 0, LAPI_SETTING_LINE_LEN);
    while (*pos != '\n')
        val[i++] = *pos++;

    //LAPI_DBG("key=%s val=%s", key, val);
    
    if (!strcmp(ATTR_LOC_METHOD, key)) {
        // location method
        if (!strcmp("STAND", val))
            g_lapi_setting.method = LAPI_LOCATION_METHOD_STANDALONE;
        else if (!strcmp("AUTO", val))
            g_lapi_setting.method = LAPI_LOCATION_METHOD_AUTONOMOUS;
        else if (!strcmp("MSA", val))
            g_lapi_setting.method = LAPI_LOCATION_METHOD_MS_ASSISTED;
        else if (!strcmp("MSB", val))
            g_lapi_setting.method = LAPI_LOCATION_METHOD_MS_BASED;
        else {
            LAPI_ERR("Bad %s=%s", key, val);
            return -1;
            goto make_default;
        }
    } else if (!strcmp(ATTR_RST_TYPE, key)) {
        // reset type
        if (!strcmp("COLD", val))
            g_lapi_setting.reset = LAPI_RESET_TYPE_COLD_RESET;
        else if (!strcmp("HOT", val))
            g_lapi_setting.reset = LAPI_RESET_TYPE_HOT_RESET;
        else if (!strcmp("FACTORY", val))
            g_lapi_setting.reset = LAPI_RESET_TYPE_FACTORY_RESET;
        else {
            LAPI_ERR("Bad %s=%s", key, val);
            return -1;
            goto make_default;
        }
    } else if (!strcmp(ATTR_SRV_ADDR, key)) {
        // server address
        strncpy(g_lapi_setting.srv_addr, val, AGPS_SRV_ADDR_LEN-1);
    } else if (!strcmp(ATTR_SRV_PORT, key)) {
        // server port
        g_lapi_setting.srv_port = strtoul(val, NULL, 10);
    } else if (!strcmp(ATTR_QOS_HOR, key)) {
        // hor_accuracy
        g_lapi_setting.qos.hor_accuracy = strtoul(val, NULL, 10);
    } else if (!strcmp(ATTR_QOS_VER, key)) {
        // ver_accuracy
        g_lapi_setting.qos.ver_accuracy = strtoul(val, NULL, 10);
    } else if (!strcmp(ATTR_QOS_TIMEOUT, key)) {
        // response timeout
        g_lapi_setting.qos.timeout = strtoul(val, NULL, 10);
    } else if (!strcmp(ATTR_FIX_INTERVAL, key)) {
        // fix interval
        g_lapi_setting.interval = strtoul(val, NULL, 10);
    } else if (!strcmp(ATTR_IMSI, key)) {
        // IMSI
        strncpy(g_lapi_setting.imsi, val, AGPS_IMSI_LEN-1);
    } else if (!strcmp(ATTR_LAC, key)) {
        // LAC
        strncpy(g_lapi_setting.lac, val, AGPS_LAC_LEN-1);
    } else if (!strcmp(ATTR_CID, key)) {
        // CID
        strncpy(g_lapi_setting.cid, val, AGPS_CID_LEN-1);
    } else if (!strcmp(ATTR_GPRS_DEV, key)) {
        // GPRS_DEV
        strncpy(g_lapi_setting.gprs_dev, val, AGPS_GPRSIF_LEN-1);
    } /*else if (!strcmp(ATTR_GPRS_PRO, key)) {
        // GPRS_PRO
        //g_lapi_setting.gprs_pro = strtoul(val, NULL, 10);
    }*/ else if (!strcmp(ATTR_CA_PATH, key)) {
        // CA Path
        strncpy(g_lapi_setting.ca_path, val, AGPS_CA_PATH_LEN-1);
    } else if (!strcmp(ATTR_ASSIST_PROTOCOL, key)) {
        // Assist Protocol
        if (!strcmp("USER_PLANE", val))
            g_lapi_setting.assist_pro = LAPI_ASSIST_PROTOCOL_USER_PLANE;
        else if (!strcmp("CONTROL_PLANE", val))
            g_lapi_setting.method = LAPI_ASSIST_PROTOCOL_CONTROL_PLANE;
        else {
            LAPI_ERR("Bad %s=%s", key, val);
            return -1;
            goto make_default;
        }
    } else if (!strcmp(ATTR_NW_OP, key)) {
        strncpy(g_lapi_setting.nw_op, val, AGPS_NW_OP_LEN-1);
    } else if (!strcmp(ATTR_NW_TYPE, key)) {
        strncpy(g_lapi_setting.nw_type, val, AGPS_NW_TYPE_LEN-1);
    } else {
        //We do nothing here.
        //LAPI_ERR("Ignore unknown setting %s=%s", key, val);
        //return -1;
        //goto make_default;
    }

    return 0;

make_default:
   // lapi_default_setting();
    lapi_copy_default_setting();
    return -1;
}

int lapi_load_setting()
{
    struct stat f_stat;
    char line_buf[LAPI_SETTING_LINE_LEN];
    FILE *fp = NULL;

    memset(&g_lapi_setting, 0, sizeof(LAPI_SETTING_S));
    memset(&g_lapi_setting_bk, 0, sizeof(LAPI_SETTING_S));

    if (stat(LAPI_SETTING_FILE, &f_stat) != 0) {
        LAPI_DBG("File %s not exist, copy the default file from the /system/location/.", LAPI_SETTING_FILE);
        return lapi_copy_default_setting();
    }

    /* make sure Java app can access */
    chmod(LAPI_SETTING_FILE, 0666);

    fp = fopen(LAPI_SETTING_FILE, "r");
    if (fp == NULL) {
        LAPI_ERR("Failed to open %s", LAPI_SETTING_FILE);
        return -1;
    }
    LAPI_DBG("Setting %s loaded", LAPI_SETTING_FILE);

    memset(line_buf, 0, LAPI_SETTING_LINE_LEN);

    int flag = 1;
    while (fgets(line_buf, LAPI_SETTING_LINE_LEN, fp) != NULL) {
        flag = 0;
        if (line_buf[0] != '\n' && line_buf[0] != '#') {
            //LAPI_DBG("line before: %s", line_buf);
            if (lapi_get_setting(line_buf) != 0) {
                LAPI_ERR("Setting %s corrupted, make default.", LAPI_SETTING_FILE);
                fclose(fp);
                return 0;
            }
        }
    }

    if(flag) {
        LAPI_DBG("cannot read config file, recover from backup buffer");
        memcpy(&g_lapi_setting, &g_lapi_setting_bk, sizeof(LAPI_SETTING_S));
    } else {
        memcpy(&g_lapi_setting_bk, &g_lapi_setting, sizeof(LAPI_SETTING_S));
    }

    fclose(fp);

    //lapi_print_setting();

    return 0;
}

